package main

import (
	"bufio"
	"github.com/hajimehoshi/ebiten/v2"
	"github.com/hajimehoshi/ebiten/v2/ebitenutil"
	"image"
	"log"
	"os"
	"strconv"
	"strings"
)

type SceneMap struct {
	// 地图宽
	mapW int
	// 地图高
	mapH int
	// 存放地图文件路径
	mapFile string
	// 源图片一行分成了几个16*16的像素块
	sourW int
	// 在空地图上绘制的X坐标
	locX int
	// 在空地图上绘制的Y坐标
	locY int
	// 绘制好等待渲染到场景中的地图
	mapFinish *ebiten.Image
	// 存放对应像素块类型，用于碰撞检测
	sliceMapTyp []string
}

func newMap(mapFile string) *SceneMap {
	sceneMap := &SceneMap{}
	// 加载地图路径
	sceneMap.mapFile = "../Map/" + mapFile + ".txt"
	sceneMap.loadMap()
	return sceneMap
}

func (sceneMap *SceneMap) loadMap() {
	// 从地图文件中获取属性
	file, err := os.Open(sceneMap.mapFile)
	if err != nil {
		log.Fatal(err)
	}
	defer func(file *os.File) {
		err := file.Close()
		if err != nil {
			log.Fatal(err)
		}
	}(file)

	scanner := bufio.NewScanner(file)

	// 读取地图宽度和高度
	scanner.Scan()
	dimensions := strings.Split(scanner.Text(), " ")
	sceneMap.mapW, _ = strconv.Atoi(dimensions[0])
	sceneMap.mapH, _ = strconv.Atoi(dimensions[1])

	// 读取sliceMapLoc的数值
	sliceMapLoc := make([]int, sceneMap.mapW*sceneMap.mapH)
	for i := 0; i < sceneMap.mapH; i++ {
		scanner.Scan()
		row := strings.Split(scanner.Text(), " ")
		for j := 0; j < sceneMap.mapW; j++ {
			sliceMapLoc[i*sceneMap.mapW+j], _ = strconv.Atoi(row[j])
		}
	}

	// 读取sliceMapTyp的数值
	sliceMapTyp := make([]string, sceneMap.mapW*sceneMap.mapH)
	for i := 0; i < sceneMap.mapH; i++ {
		scanner.Scan()
		row := strings.Split(scanner.Text(), " ")
		for j := 0; j < sceneMap.mapW; j++ {
			sliceMapTyp[i*sceneMap.mapW+j] = row[j]
		}
	}

	sceneMap.sliceMapTyp = sliceMapTyp
	// 初始化图片
	ImageFences, _, err := ebitenutil.NewImageFromFile("../Image/Tilesets/Fences.png")
	if err != nil {
		log.Fatal(err)
	}
	ImageGrass, _, err := ebitenutil.NewImageFromFile("../Image/Tilesets/Grass.png")
	if err != nil {
		log.Fatal(err)
	}
	ImageHills, _, err := ebitenutil.NewImageFromFile("../Image/Tilesets/Hills.png")
	if err != nil {
		log.Fatal(err)
	}
	ImageWater, _, err := ebitenutil.NewImageFromFile("../Image/Tilesets/Water.png")
	if err != nil {
		log.Fatal(err)
	}
	ImageTilled, _, err := ebitenutil.NewImageFromFile("../Image/Tilesets/TilledDirt.png")
	if err != nil {
		log.Fatal(err)
	}
	ImageWoodenHouse, _, err := ebitenutil.NewImageFromFile("../Image/Tilesets/WoodenHouse.png")
	if err != nil {
		log.Fatal(err)
	}

	// 根据位置切片和类型切片渲染像素图块
	var Image *ebiten.Image
	var drawType *ebiten.Image
	mapFinish := ebiten.NewImage(sceneMap.mapW*16, sceneMap.mapH*16)
	// 在渲染除了草块和水的像素块时，需要先渲染草块
	var isDrawGrass bool = false
	for i := 0; i < len(sliceMapLoc); i++ {
		mapX := (sceneMap.locX + i) % sceneMap.mapW
		mapY := (sceneMap.locY + i) / sceneMap.mapW

		var mapFileType = sliceMapTyp[i]
		switch mapFileType {
		case "f":
			drawType = ImageFences
			sceneMap.sourW = 4
			isDrawGrass = true
		case "g":
			drawType = ImageGrass
			sceneMap.sourW = 6
		case "h":
			drawType = ImageHills
			sceneMap.sourW = 6
		case "t":
			drawType = ImageTilled
			sceneMap.sourW = 6
		case "o":
			drawType = ImageWoodenHouse
			sceneMap.sourW = 6
			isDrawGrass = true
		case "w":
			drawType = ImageWater
			sceneMap.sourW = 4
		case "n":
			// 类型为空时代表空地块
			continue
		default:
			log.Fatal("nil Image!")
		}

		x0 := (sliceMapLoc[i] - 1) % sceneMap.sourW * 16
		y0 := (sliceMapLoc[i] - 1) / sceneMap.sourW * 16
		Image = drawType.SubImage(image.Rect(x0, y0, x0+16, y0+16)).(*ebiten.Image)
		op := &ebiten.DrawImageOptions{}
		op.GeoM.Translate(float64(mapX*16), (float64)(mapY*16))
		if isDrawGrass {
			mapFinish.DrawImage(ImageGrass.SubImage(image.Rect(0, 0, 16, 16)).(*ebiten.Image), op)
		}
		mapFinish.DrawImage(Image, op)
		isDrawGrass = false
	}
	sceneMap.mapFinish = mapFinish
}
